/**
 * TManActiveThread.java
 * ************************** 
 * @date May 5, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package gossipServices.bootstraping.tman;

import gossipServices.basic.nodeDescriptors.NodeDescriptor;
import gossipServices.basic.view.ConcretePartialView;
import gossipServices.basic.view.PartialView;
import gossipServices.gossipMessages.TManMessage;
import gossipServices.gossipThread.ActiveGossipThreadInterface;
import gossipServices.pss.PeerSamplingServiceAPI;
import messages.Message;

/**
 * Description:
 * It's the active thread of TMan. It extends the {@link TManMiddleware}
 * in order to share with the passive thread the shared variables.
 * It implements the {@link ActiveGossipThreadInterface}.
 *
 */
public class TManActiveThread extends TManMiddleware implements
		ActiveGossipThreadInterface {
	
	/**
	 * @param string
	 * @param cycleLengthMsec
	 * @param tManView
	 * @param pss
	 * @param tmanNm
	 * @param localNodeDescriptor
	 * @param rankingMet
	 * @param messageSize
	 * @param phi2
	 */
	public TManActiveThread(String name, long cycleLengthMsec,
			PartialView initView, PeerSamplingServiceAPI pss,
			TManNetworkManager tmanNm, NodeDescriptor localNodeDescriptor,
			TManRankingMethod rankingMet, int messageSize, int phi, int tabuListSize, String subcloudID) {
		super(name, cycleLengthMsec, initView, pss, tmanNm,localNodeDescriptor, rankingMet, 
				messageSize, phi, tabuListSize, subcloudID);
		gossipProtocol = this;
	}

	@Override
	public void activeThreadInstructions() throws InterruptedException {
		NodeDescriptor p = null;
		PartialView buffer = new ConcretePartialView(0);
		synchronized (view) {
			/* HINT: if maintenance is needed we can try to improve the
			 * localView with additional peers piked up from the 
			 * PeerSamplingService and merge them in the local view.
			*/
			p = selectPeer(psi, ranker.rank(myDescriptor, view));
//			System.out.println(this.getClass().getSimpleName()+" selected peer: "+p);
			buffer.merge(view);
			buffer.insertNodeDescriptor(myDescriptor);
			// -----------------------------------------
//			buffer = ranker.rank(p, buffer); <- modification from the code in the paper (**)
			// -----------------------------------------
		}
		if(tabuListCheck(p)){
			tabuList.add(p);
//			System.out.println("TABU LIST:\n"+tabuList);
			Message msg = new TManMessage(myDescriptor, p, 
					buffer.head(m), TManActiveThread.class, subcloudID);
//			System.out.println("ACTIVE: sending-> "+msg);
			netServ.send(msg, p);
			Message msgP = netServ.receive(p); 
			//		System.out.println("ACTIVE: receiving-> "+msgP);
			if( msgP != null ){
				PartialView bufferP = (PartialView) msgP.getBody();
				synchronized (view) {
					view.merge(bufferP);
					// ----------------------------------
					view = ranker.rank(myDescriptor, view); // <- (**) this is an addition respect to the paper
					// line marked with (**) is translated in the above instruction
					// ----------------------------------
					cycles++;
					debugPrint();
				}
			}
		}
		terminationCheck();
		/*
		 * NOTE: (**)
		 * In the paper "T-Man: Gossip-based fast overlay topology construction"
		 * of 2009 the algorithm finishes with the merging of view
		 * by bufferP at line 79.
		 * I added the (**) instruction, at line 81, following the previous paper:
		 * "T-Man: Gossip-based overlay topology management", (2006),
		 * where they used the function: "view <- selectView(bufferP)".
		 * In this way a node locally is able to update its view according
		 * to the specified ranking method, instead of only receiving
		 * the bufferP in the message and merge as it is into the view.
		 * I think that this modification can improve the robustness of the algorithm
		 * to the joining of new nodes and the removal of some nodes in the overlay.
		 *	  
		 */
	}


	@Override
	public void gossipThreadInstructions() throws InterruptedException {
		activeThreadInstructions();
	}

}
